#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include "digraph.h"
#include "pagerank.h"
#include "hits.h"
#include "stats.h"
#include "vector.h"

#define PAGERANK 0
#define HITS 1

Digraph
read_input ();

int
check_answer (double*, Digraph, double, double);

int main(int argc, char* argv[])
{
  Digraph H;
  int algorithm, arg_index, rank_index, top, result, zero_dist, max_dist, pos_max;
  int **rank;
  double *pi, *aut, *hub;
  double epsilon, arg;

  H = read_input();
  arg_index = 1;
  algorithm = 0;
  max_dist = 0;

  // Read arguments
  top = atoi(argv[arg_index++]);

  // Memory allocation
  pi = malloc(H->V * sizeof(double));
  aut = malloc(H->V * sizeof(double));
  hub = malloc(H->V * sizeof(double));
  rank = malloc(((argc - 2) / 2 ) * sizeof(int *));

  epsilon = 0.000001;
  rank_index = result = 0;

  while (arg_index < argc) {
    if (strcmp(argv[arg_index], "-p") == 0) algorithm = PAGERANK;
    else if (strcmp(argv[arg_index], "-ha") == 0) {
      algorithm = HITS;
      result = 0;
    }
    else if (strcmp(argv[arg_index], "-hh") == 0) {
      algorithm = HITS;
      result = 1;
    }
    else printf("Incorrect usage!\n");
    arg_index++;
    arg = atof(argv[arg_index++]);
    // Algorithms
    switch (algorithm) {
      case PAGERANK:
        // Compute PageRank
        rank[rank_index++] = pagerank_pm(pi, H, arg, epsilon);
        break;
      case HITS:
        // Compute HITS
        rank[rank_index++] = hits_pm(H, arg, epsilon, aut, hub, result);
        break;
      default:
        printf("ERROR: This program should not have entered here!\n");
        return 2;
        break;
    }
  }
  //printf("Resposta == %d\n", check_answer(pi, H, alpha, epsilon));
  zero_dist = same_index(rank[0], rank[1], H->V, top, &max_dist, &pos_max);
  printf("%d results did not change position.\n", zero_dist);
  printf("Max dist: %d @ position %d\n", max_dist, pos_max);

  // Free routines
  free(pi);
  free(aut);
  free(hub);
  DIGRAPHfree(H);
  for (arg_index = 0; arg_index < ((argc - 2) / 2); arg_index++) {
    free(rank[arg_index]);
  }
  free(rank);

  // Terminate program
  return 0;
}

//Functions

Digraph read_input ()
{
  Digraph H;
  Vertex v, w;
  int V;

  scanf("%d", &V);
  H = DIGRAPHinit(V);
  scanf("%d:", &v);
  while (v < H->V) {
    scanf("%d", &w);
    while (w != -1) {
      DIGRAPHinsertA(H, v, w);
      scanf("%d", &w);
    }
    scanf("%d:", &v);
  }
  return H;
}

int check_answer (double* pi, Digraph H, double alpha, double epsilon)
{
  double *ans;
  double inner, value;
  Vertex v;
  link list;

  ans = malloc(H->V * sizeof(double));
  for (v = 0; v < H->V; v++) ans[v] = 0.0;

  for (v = 0; v < H->V; v++) {
    list = H->adj[v];
    while (list != NULL) {
      ans[list->w] += pi[v] * (1.0 / H->out[v]) * alpha;
      list = list->next;
    }
  }

  inner = inner_product(pi, H->dng, H->V);
  value = (1.0 / H->V) * ((alpha * inner) + (1.0 - alpha));

  for (v = 0; v < H->V; v++) {
    ans[v] += value;
    if (fabs(pi[v] - ans[v] > epsilon)) {
      printf("ans[%d] = %f\npi[%d] = %f\n", v, ans[v], v, pi[v]);
      free(ans);
      return 0;
    }
  }
  free(ans);
  return 1;
}

